package com.kexio.user.mapper;

import java.time.LocalDateTime;
import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kexio.user.entity.User;

/**
 * 用户数据访问层
 * 
 * 基于MyBatis Plus的用户数据访问接口，提供：
 * - 基础CRUD操作（继承自BaseMapper）
 * - 用户认证查询
 * - 权限聚合查询
 * - 用户状态管理
 * - 多租户数据隔离
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {
    
    // ==================== 认证相关查询 ====================
    
    /**
     * 根据用户名和租户ID查询用户信息
     * 
     * @param username 用户名
     * @return 用户信息
     */
    User selectByUsernameAndTenant(@Param("username") String username);
    
    /**
     * 根据手机号和租户ID查询用户信息
     * 
     * @param phone 手机号
     * @param tenantId 租户ID
     * @return 用户信息
     */
    User selectByPhoneAndTenant(@Param("phone") String phone);
    
    /**
     * 根据邮箱和租户ID查询用户信息
     * 
     * @param email 邮箱
     * @return 用户信息
     */
    User selectByEmailAndTenant(@Param("email") String email);
    
    // ==================== 权限聚合查询 ====================
    
    /**
     * 查询用户的所有权限编码
     * 
     * 通过用户角色关联查询用户拥有的所有权限编码
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 权限编码列表
     */
    List<String> selectUserPermissions(@Param("userId") String userId);
    
    /**
     * 查询用户的所有角色ID
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 角色ID列表
     */
    List<String> selectUserRoles(@Param("userId") String userId);
    
    /**
     * 查询用户的菜单树结构
     * 
     * 根据用户权限构建个人菜单树
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 菜单信息列表（父子关系需要在Service层构建）
     */
    List<com.kexio.user.entity.Menu> selectUserMenus(@Param("userId") String userId);
    
    /**
     * 批量查询用户及其角色（一条SQL搞定，直接返回User with List<Role>）
     * MyBatis会自动通过collection标签组装每个User的角色列表
     * 
     * @param userIds 用户ID列表
     * @return 用户列表，每个User对象的roles字段已填充
     */
    List<User> selectUsersWithRoles(@Param("userIds") List<String> userIds);
    
    // ==================== 状态管理 ====================
    
    // 通用更新/统计放在 Mapper 默认方法，供 Service 复用（使用 MP Wrapper 实现）
    default int updateLastLoginTimeById(String userId, LocalDateTime lastLoginTime) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .set(User::getLastLoginTime, lastLoginTime)
                     .set(User::getUpdateTime, LocalDateTime.now());
        return this.update(null, updateWrapper);
    }
    
    default int updatePasswordErrorCountById(String userId, int errorCount) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .set(User::getPasswordErrorCount, errorCount)
                     .set(User::getUpdateTime, LocalDateTime.now());
        return this.update(null, updateWrapper);
    }
    
    default int incrementPasswordErrorCountById(String userId) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .setSql("password_error_count = COALESCE(password_error_count, 0) + 1")
                     .set(User::getUpdateTime, LocalDateTime.now());
        return this.update(null, updateWrapper);
    }
    
    default int clearPasswordErrorCountById(String userId) {
        return updatePasswordErrorCountById(userId, 0);
    }
    
    default int lockUserById(String userId, LocalDateTime lockTime, LocalDateTime unlockTime) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .set(User::getLockTime, lockTime)
                     .set(User::getUnlockTime, unlockTime)
                     .set(User::getUpdateTime, lockTime);
        return this.update(null, updateWrapper);
    }
    
    default int unlockUserById(String userId) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .set(User::getLockTime, null)
                     .set(User::getUnlockTime, null)
                     .set(User::getPasswordErrorCount, 0)
                     .set(User::getUpdateTime, LocalDateTime.now());
        return this.update(null, updateWrapper);
    }
    
    default int updatePermVersionById(String userId, Long permVersion) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                     .set(User::getPermVersion, permVersion)
                     .set(User::getUpdateTime, LocalDateTime.now());
        return this.update(null, updateWrapper);
    }
    
    /**
     * 批量更新用户权限版本号
     * 
     * @param userIds 用户ID列表
     * @param permVersion 新的权限版本号
     * @return 更新的记录数
     */
    int batchUpdatePermVersion(@Param("userIds") List<String> userIds, @Param("permVersion") Long permVersion);
    
    // ==================== 统计查询 ====================
    
    default long countUsersByTenantId(String tenantId) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        return this.selectCount(wrapper);
    }
    
    default long countActiveUsersByTenantId(String tenantId, LocalDateTime threshold) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(User::getLastLoginTime, threshold);
        return this.selectCount(wrapper);
    }
    
    // ==================== 部门相关查询 ====================
    
    /**
     * 查询部门下的所有用户
     * 
     * @param deptId 部门ID
     * @param tenantId 租户ID
     * @return 用户列表
     */
    List<User> selectUsersByDept(@Param("deptId") String deptId);
    
    /**
     * 查询部门及其子部门下的所有用户
     * 
     * @param deptIds 部门ID列表（包含子部门）
     * @param tenantId 租户ID
     * @return 用户列表
     */
    List<User> selectUsersByDepts(@Param("deptIds") List<String> deptIds);
    
    /**
     * 批量查询用户数据权限范围内的用户
     * 
     * 根据数据权限类型和用户权限范围查询可见用户
     * 
     * @param currentUserId 当前用户ID
     * @param dataScopeType 数据权限类型
     * @param deptIds 部门ID列表（数据权限范围）
     * @param tenantId 租户ID
     * @return 用户列表
     */
    List<User> selectUsersInDataScope(@Param("currentUserId") String currentUserId, 
                                      @Param("dataScopeType") String dataScopeType,
                                      @Param("deptIds") List<String> deptIds);
}
